package xfuzzy.alg_genetico.indeterminado.xfghlOld.model;

import xfuzzy.lang.Specification;
import xfuzzy.lang.XflException;
//import xfuzzy.xfedit.Xfedit;
import xfuzzy.xfhl.model.XfhlData;
import xfuzzy.xfsl.model.XfslAlgorithm;
import xfuzzy.xfsl.model.XfslAlgorithmFactory;
import xfuzzy.xfsl.model.XfslConfig;
import xfuzzy.xfsl.model.XfslEndCondition;
import xfuzzy.xfsl.model.XfslErrorFunction;
import xfuzzy.xfsl.model.XfslThread;
import xfuzzy.xfsl.model.algorithm.Marquardt;
import xfuzzy.xfsl.model.algorithm.RProp;
import xfuzzy.xfsl.model.algorithm.XfslGradientBasedAlgorithm;


/**
 * Clase que es ajusta una especificiacion
 * @author Sergio
 *
 */
public class XfghlThread extends Thread {
			
	
	/**
	 * Identificador de la hebra
	 */
	private int idThread;
	
	/**
	 * Configuracion del mudulo Xfhl
	 */
	private XfghlConfig confXfhl;
	
	/**
	 * Instancia del xfhlData que va a utilizar la hebra
	 */
	private XfhlData data;
	
	/**
	 * Constructor
	 * @param idThread Identificador de la Hebra
	 * @param conf Configuracion de la herramienta XfhlConfig
	 * @param data XfhlData que utilizara la hebra
	 */
	public XfghlThread(int idThread, XfghlConfig conf, XfhlData data)  {
		
		this.idThread = idThread;
		this.confXfhl = conf;
		this.data = data;		
	}
			
	/**
	 * Ejecucion de la hebra
	 */
	public void run() {
		
	   //Cromosoma a entrenar	
       XfghlChromosome chrom = null;
	   
	   while ((chrom = XfghlLearnSpecif.getChromosome()) != null)  {
		   
		   //Asignamos como entrenada
		   chrom.setLearned(true);
		   System.out.println("Hebra " + this.idThread + ". Entrenando: " + chrom.toString());
		   Specification spec = chrom.getSpecification();
		   //Ajustamos la especificacion
		   this.data.setSpec(spec);
		   //Xfedit edit=new Xfedit(null,spec);
		   //edit.setVisible(true);
		   learning(spec);				
	       //Asignamos al cromosoma el error cometido
		   chrom.setFinalError(this.data.getFinalError());
		   System.out.println(this.idThread + " " + chrom.toString() + " " + chrom.getFinalError());
		   
		   //Liberamos memoria
		   chrom.setHierStruct(null);
		   chrom.setSpecification(null);

	   }
		System.out.println("Soy la hebra " + this.idThread + " y he terminado.");
	}
	
	/**
	 * Ajusta las salidas del sistema con el algoritmo aprendizaje
	 */
	private  void learning(Specification spec) {
					    								
		XfslThread lrnthread = new XfslThread(spec, createtXfslConfig());
		
		//Añadimos al objeto data como observador para notificarle los cambios
		lrnthread.addObserver(this.data);
		
		try {
			lrnthread.tuning();
		} 
		catch (XflException e) {
			// Auto-generated catch block
			e.printStackTrace();
		}				
	}

	
	/**
	 * Crea una configuraci�n para la herramienta de ajuste con la configuraci�n de la herramienta Xfhl
	 * @return La configuraci�n de la herramienta Xfsl 
	 */
	private XfslConfig createtXfslConfig()
	{
		XfslConfig xfslConfig=new XfslConfig();
		
		//Parametros del algoritmo
		double param[] = { this.confXfhl.getIniUpd(),this.confXfhl.getIncFact(),this.confXfhl.getDecFact()};
		
		int alg=-1;
		int err = XfslErrorFunction.MEAN_SQUARE_ERROR;
		int end = XfslEndCondition.EPOCH;

		if(this.confXfhl.getAlgorithm()==0)
		{
			alg = XfslAlgorithm.RPROP;
			
			RProp rprop;
			try {
				rprop = (RProp)XfslAlgorithmFactory.createAlgorithm(alg, param);
			    //rprop.setOption(RProp.COMPUTE, this.confXfhl.getPerturbation());
				rprop.setOption(RProp.COMPUTE,XfslGradientBasedAlgorithm.COMPUTE);
			    xfslConfig= new XfslConfig();		
			    xfslConfig.trainingfile = this.confXfhl.getDataSetFile();
			    xfslConfig.algorithm =rprop; 
			    xfslConfig.errorfunction = new XfslErrorFunction(err);
			    xfslConfig.endcondition.setLimit(end,this.confXfhl.getnumIterAjust());
				
			} catch (XflException e) {
				// Auto-generated catch block
				e.printStackTrace();
			}					
		}
		else if (this.confXfhl.getAlgorithm()==1)
		{
			
			alg = XfslAlgorithm.MARQUARDT;			
			Marquardt marq;
			try {
				marq = (Marquardt)XfslAlgorithmFactory.createAlgorithm(alg, param);
				//marq.setOption(Marquardt.COMPUTE, this.confXfhl.getPerturbation());
				marq.setOption(Marquardt.COMPUTE,0);
			    xfslConfig= new XfslConfig();		
			    xfslConfig.trainingfile = this.confXfhl.getDataSetFile();
			    xfslConfig.algorithm =marq;
			    xfslConfig.errorfunction = new XfslErrorFunction(err);
			    xfslConfig.endcondition.setLimit(end,this.confXfhl.getnumIterAjust());
			    
				
			} catch (XflException e) {
				// Auto-generated catch block
				e.printStackTrace();
			}	
		}
			
		return xfslConfig;		
	}
	
	/**
	 *  GETTERS AND SETTERS 
	 * */		
	public XfhlData getData()
	{
		return this.data;	
	}

}
